﻿#region Creditos

/* Autor: Edilberto Sánchez Forero	*/
/* Email: esanchezfo@gmail.com		*/
/* Licencia: LGPL, Software Libre	*/
/* País: Colombia, Bogotá			*/

#endregion

#region Librerias

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Threading;
using System.Xml;

using ESF.Object.XmlRepresenter;
using ESF.General;
using ESF.Object.SolutionGenerator.Services.Core;
using ESF.Object.SolutionGenerator.Web;
using ESF.Object.DataBaseGenerator;

#endregion


namespace ESF.Object.SolutionGenerator
{
	#region Enumeraciones
		
	public enum CompilerTypes
	{
		Mono,
		MSdotNET
	}
	
	#endregion	


	public static class SolGenerator
	{
		#region Constantes
		
		private const double MONO_MIN_VERSION = 2.4;
		
		private const byte MSDOTNET_MIN_VERSION = 2;
		
		#endregion
		
		
		#region Delegados
		
		internal delegate void GenerateClass (TextWriter txtWriter, string pstrBaseNamespace, string pstrBaseClassName, XmlObject pobjObject);
		
		#endregion
	
	
		#region Miembros
		
		private static StringBuilder _References;
		
		private static string _Namespace;
		private static string _ConnectionStringName;
		private static string _LibrariesDestinationFolder;
		private static string _ReferenceAssembliesFolder;
		private static string _SourcesDestinationFolder;
		
		private static string _DbParamsSeparator;
		private static string _DbNamesSeparator;
		private static string _DbName;
		
		private static string _MonoBinPath;
		private static string _MSVstudioSDKBinPath;
		
		private static XmlObjectSetManager _ObjectSetManager;
		
		public static bool DoCompile;
		private static bool _GenerateWebControls;
		
		private static uint? _CompileMaxWaitMilliseconds;
		
		private static CompilerTypes? _CompilerType = CompilerTypes.Mono;
		
		private static Validate _Validate;
		
		#endregion
		
		
		#region Propiedades
		
		public static bool GenerateWebControls
		{
			get { return SolGenerator._GenerateWebControls; }
			set
			{
				if (!SolGenerator.DoCompile && SolGenerator.GenerateWebControls)
				{
					throw new GenericException (GenericException.CRI_INVALID_PARAMETER, "El atributo doCompile debe estar en true habilitando la compilacion del las librerias para asi poder generar los controles web");
				}
				
				SolGenerator._GenerateWebControls = value;
			}
		}
		
		public static uint CompileMaxWaitMilliseconds 
		{
			get 
			{
				if (SolGenerator._CompileMaxWaitMilliseconds == null) { return 0; }
				
				return SolGenerator._CompileMaxWaitMilliseconds.Value; 
			}
		}
		
		
		private static Validate Validate
		{
			get
			{
				if (SolGenerator._Validate == null)
				{
					SolGenerator._Validate = new Validate ();
					SolGenerator._Validate.ObjectName = "Generador de Soluciones de ROSSOX";
				}
				
				return SolGenerator._Validate;
			}
		}
		
		public static XmlObjectSetManager ObjectSetManager
		{
			set { SolGenerator._ObjectSetManager = value; }
			get { return SolGenerator._ObjectSetManager; }
		}
				
		public static CompilerTypes? CompilerType
		{
			set 
			{
				SolGenerator._CompilerType = value; 
				SolGenerator.ClearReferences (); 
			}
			get 
			{
				if (SolGenerator._CompilerType == null)
				{
					return CompilerTypes.MSdotNET;
				}
				
				return SolGenerator._CompilerType; 
			}
		}
				
		public static string ConnectionStringName
		{
			get 
			{
				return SolGenerator._ConnectionStringName;
			}
			set
			{
				SolGenerator.Validate.Filled (true, "Nombre de la Cadena de Conexión", value);
				
				SolGenerator._ConnectionStringName = value;
			}
		}
		
		public static string LibrariesDestinationFolder
		{
			get 
			{
				if (string.IsNullOrEmpty (SolGenerator._LibrariesDestinationFolder))
				{
					return string.Empty;
				}
			
				return SolGenerator._LibrariesDestinationFolder;
			}
			set
			{
				SolGenerator._LibrariesDestinationFolder = value;
				
				FileHelper.EnsureFolder (value);
			}
		}
		
		public static string SourcesDestinationFolder
		{
			get 
			{
				if (string.IsNullOrEmpty (SolGenerator._SourcesDestinationFolder))
				{
					return Path.GetTempPath ();
				}
			
				return SolGenerator._SourcesDestinationFolder;
			}
			set
			{
				SolGenerator._SourcesDestinationFolder = value;
				
				FileHelper.EnsureRecreateFolder (value);
			}
		}
		
		public static string ReferenceAssembliesFolder
		{
			get
			{
				return SolGenerator._ReferenceAssembliesFolder;
			}
			set
			{
				SolGenerator._ReferenceAssembliesFolder = value;
			}
		}
		
		public static string DbParamsSeparator
		{
			get { return SolGenerator._DbParamsSeparator; }
			set { SolGenerator._DbParamsSeparator = value; }
		}
		
		public static string DbNamesSeparator
		{
			get { return SolGenerator._DbNamesSeparator; }
			set { SolGenerator._DbNamesSeparator = value; }
		}
		
		public static string DbName
		{
			get 
			{
				return SolGenerator._DbName; 
			}
			set 
			{
				SolGenerator.Validate.Filled (true, "Nombre de la Base de Datos", value);
				
				SolGenerator._DbName = value; 
			}
		}
		
		public static string Namespace
		{
			get 
			{
				return SolGenerator._Namespace;
			}
			set
			{
				SolGenerator.Validate.Filled (true, "Espacio de Nombres", value);
				
				SolGenerator._Namespace = value;
			}
		}
		
		public static string MonoBinPath
		{
			get
			{
				SolGenerator.Validate.DirectoryExists (true, "Ruta de los ejecutables de Mono", SolGenerator._MonoBinPath);
				
				return SolGenerator._MonoBinPath;
			}
			set
			{
				SolGenerator._MonoBinPath = FileHelper.AddFinalSeparator (value);
			}
		}
		
		public static string MSVstudioSDKBinPath
		{
			get
			{
				SolGenerator.Validate.DirectoryExists (true, "Ruta de los ejecutables del SDK de MS Visual Studio", SolGenerator._MSVstudioSDKBinPath);
				
				return SolGenerator._MSVstudioSDKBinPath;
			}
			set
			{
				SolGenerator._MSVstudioSDKBinPath = FileHelper.AddFinalSeparator (value);
			}
		}
		
		
		
		
		#endregion
		
		
		#region Funciones para el manejo de referencias
		
		internal static void AddReference (string pstrFileName, bool pblnValidate)
		{
			if (pblnValidate)
			{
				SolGenerator.Validate.FileExists (true, "Assemblie de referencia para compilación", pstrFileName);
			}
		
			if (SolGenerator.CompilerType == CompilerTypes.MSdotNET)
			{
				SolGenerator._References.AppendFormat (@" /reference:""{0}""", pstrFileName);
			}
			else
			{
				SolGenerator._References.AppendFormat (@" -r:""{0}""", pstrFileName);
			}
		}
		
		
		internal static void ClearReferences ()
		{
			SolGenerator._References = new StringBuilder ();
		}
		
		#endregion
		
		
		#region Funciones de Generacion Comun de Archivos
		
		internal static void GenerateAssemblyInfo 
		(
			DirectoryInfo pdirDestinationFolder, 
			string pstrTitle, string pstrDescription, 
			string pstrBaseNamespace, string pstrVersion
		)
		{
			SolGenerator.GenerateAssemblyInfo (pdirDestinationFolder, pstrTitle, pstrDescription, pstrBaseNamespace, pstrVersion, false);
		}

		
		internal static void GenerateAssemblyInfo 
		(
			DirectoryInfo pdirDestinationFolder, 
			string pstrTitle, string pstrDescription, 
			string pstrBaseNamespace, string pstrVersion,
			bool pblnAddTagPrefix
		)
		{
			TextWriter txtWriter;
			
		
			txtWriter = null;
		
			try
			{
				txtWriter = File.CreateText (pdirDestinationFolder.FullName + Path.DirectorySeparatorChar + "AssemblyInfo.cs");
				
				txtWriter.WriteLine ("using System.Reflection;");
				txtWriter.WriteLine ("using System.Runtime.CompilerServices;");
				txtWriter.WriteLine ("using System.Runtime.InteropServices;\n\n");
				
				if (pblnAddTagPrefix)
				{
					txtWriter.WriteLine ("using System.Web.UI;");
					txtWriter.WriteLine (@"[assembly:TagPrefix (""{0}"", ""{0}"")]", pstrBaseNamespace);
				}
				
				txtWriter.WriteLine (@"[assembly: AssemblyTitle (""{0}"")]", pstrTitle);
				txtWriter.WriteLine (@"[assembly: AssemblyDescription (""{0}"")]", pstrDescription);
				txtWriter.WriteLine (@"[assembly: AssemblyCompany (""Generated by ROSSOX with {0} compiler, ROSSOX was created by Edilberto Sanchez Forero, esanchezfo@gmail.com"")]", SolGenerator.CompilerType);
				txtWriter.WriteLine (@"[assembly: AssemblyProduct (""{0}"")]", pstrBaseNamespace);
				txtWriter.WriteLine (@"[assembly: AssemblyCopyright (""Copyright © {0}, ROSSOX"")]", DateTime.Now.Year);
				txtWriter.WriteLine (@"[assembly: AssemblyTrademark (""{0}"")]", pstrBaseNamespace);

				txtWriter.Write ("\n\n");
				txtWriter.WriteLine (@"[assembly: AssemblyVersion (""{0}"")]", pstrVersion);
				txtWriter.WriteLine (@"[assembly: AssemblyFileVersion (""{0}"")]", pstrVersion);
			}
			catch (Exception excEx)
			{
				throw new GenericException (GenericException.CRI_FILE_ERROR, string.Format ("No pudo ser generado el AssemblyInfo.cs para {0} debido a: {1}", pstrBaseNamespace, excEx.Message), excEx);
			}
			finally
			{
				if (txtWriter != null)
				{
					txtWriter.Close ();
				}
			}
		}
		
		#endregion
		
		
		#region Funciones de Compilacion
		
		internal static void GenerateCallCompiler 
		(
			string pstrSourcesDirectory, string pstrSetName, string pstrLibraryName,
			string pstrSNKFileName, ref List<ProcessStartInfo> pobjCompileCalls
		)
		{
			string strArguments;
			
			string strRuntimeFolder;
			string strSDKFolder;
			
			ProcessStartInfo proInfo;
			
		
			if (SolGenerator.CompilerType == CompilerTypes.Mono)
			{
				strArguments = @"-out:""{0}.dll"" -recurse:""{1}*.cs"" -target:library -optimize -pkg:dotnet {2} -keyfile:""{3}"""; 
					
			}
			else
			{
				strArguments = @"/out:""{0}.dll"" /target:library /recurse:""{1}*.cs"" /optimize {2} /keyfile:""{3}""";
			}
			
			strArguments = string.Format (strArguments, 
				SolGenerator.LibrariesDestinationFolder + Path.DirectorySeparatorChar + SolGenerator.Namespace + "." + pstrSetName + "." + pstrLibraryName, 
				pstrSourcesDirectory + Path.DirectorySeparatorChar, SolGenerator._References.ToString (), pstrSNKFileName);
			
			proInfo = new ProcessStartInfo ();
			
			SolGenerator.GetRuntimeToolsFolders (out strSDKFolder, out strRuntimeFolder);
			
			proInfo.FileName = strRuntimeFolder;
			
			if (SolGenerator.CompilerType == CompilerTypes.Mono)
			{
				proInfo.FileName += "gmcs.bat";
			}
			else
			{
				proInfo.FileName += "csc.exe";
			}
			
			proInfo.Arguments = strArguments;
			
			pobjCompileCalls.Add (proInfo);
			
			
			SolGenerator.AddReference (string.Format (@"{0}.dll", 
				SolGenerator.LibrariesDestinationFolder + Path.DirectorySeparatorChar + 
				SolGenerator.Namespace + "." + pstrSetName + "." + pstrLibraryName), false);
		}
		
		
		internal static void GetRuntimeToolsFolders (out string pstrSDKFolder, out string pstrFolderRuntime)
		{
			if (SolGenerator.CompilerType == CompilerTypes.MSdotNET)
			{
				if (Environment.Version.Major < SolGenerator.MSDOTNET_MIN_VERSION)
				{
					throw new GenericException (GenericException.CRI_UNSUPPORTED_ENVIRONMENT, string.Format ("Se requiere como mínimo Microsoft .NET {0} pero se tiene versión {1}", SolGenerator.MSDOTNET_MIN_VERSION, Environment.Version));
				}
			
				if (Environment.OSVersion.Platform == PlatformID.Win32Windows ||
					Environment.OSVersion.Platform == PlatformID.Win32NT)
				{
					pstrFolderRuntime = Environment.GetEnvironmentVariable ("windir") + @"\Microsoft.NET\Framework\v2.0.50727\";
					pstrSDKFolder = SolGenerator.MSVstudioSDKBinPath;
				}
				else
				{
					throw new GenericException (GenericException.CRI_UNSUPPORTED_ENVIRONMENT, string.Format ("La plataforma {0} no esta identificada como una definida para compilar con Microsoft .NET", Environment.OSVersion));
				}
			}
			else
			{
				if (Environment.Version.Major < SolGenerator.MONO_MIN_VERSION)
				{
					throw new GenericException (GenericException.CRI_UNSUPPORTED_ENVIRONMENT, string.Format ("Se requiere como mínimo Mono {0} pero se tiene versión {1}", SolGenerator.MONO_MIN_VERSION, Environment.Version));
				}
				
				pstrFolderRuntime = SolGenerator.MonoBinPath;
				pstrSDKFolder = pstrFolderRuntime;
			}
		}
				
		#endregion
		
	
		#region Funciones de Generacion
		
		public static void GenerateVStudioSolution (string pstrDestinationFolder)
		{
			// TODO: Generar un proyecto en blanco con los componentes necesarios
		}
		
		
		public static void GenerateLibraries ()
		{
			DirectoryInfo dirDestinationFolder;
			
			List<ProcessStartInfo> objCompileCalls;
			
			
			SolGenerator.ClearReferences ();
		
			// TODO: Generar la version del archivo bat para linux, sh
			objCompileCalls = new List<ProcessStartInfo> ();
			
			dirDestinationFolder = new DirectoryInfo (SolGenerator.SourcesDestinationFolder);
		
		
			try
			{
				SolGenerator.AddReference (string.Format (@"{0}{1}ESF.General.dll", 
					SolGenerator.ReferenceAssembliesFolder, Path.DirectorySeparatorChar), true);
					
				SolGenerator.AddReference (string.Format (@"{0}{1}ESF.Data.dll", 
					SolGenerator.ReferenceAssembliesFolder, Path.DirectorySeparatorChar), true);
				
				
				foreach (XmlObjectSet objSet in SolGenerator._ObjectSetManager.ObjectSets)
				{
					SolGenerator.GenerateClasses ("Entities", 
						objSet.Objects.FindAll (o => !o.IsArray), objSet.Name, objSet.Version, string.Empty,
						EntityGenerator.GenerateClass, ref objCompileCalls);

					SolGenerator.GenerateClasses ("DataAccesses", 
						objSet.Objects.FindAll (o => !o.IsArray), objSet.Name, objSet.Version, "BaseAdo", 
						DataAccessGenerator.GenerateClass, ref objCompileCalls);

					DataAccessGenerator.GenerateGeneralClass (objSet.Name);

					SolGenerator.GenerateClasses ("Controllers", 
					  	objSet.Objects.FindAll (o => !o.IsArray), objSet.Name, objSet.Version, "BaseCtrl", 
						ControllerGenerator.GenerateClass, ref objCompileCalls);
				}
			}
			catch (GenericException excEx)
			{
				throw excEx;
			}
			catch (Exception excEx)
			{
				throw new GenericException (GenericException.CRI_FOLDER_ERROR, string.Format ("No fue generada la estructura de directorios para la generación de librerias en {0}", dirDestinationFolder.FullName), excEx);
			}
			
			
			ServerControlWebGenerator.GenerateWebControls (ref objCompileCalls);
			
			SolGenerator.Compile (objCompileCalls);
		}
		
		
		private static void Compile (List<ProcessStartInfo> pobjCompileCalls)
		{
			if (SolGenerator.DoCompile)
			{
				Console.WriteLine ("\n\nCompilando las librerias...\n");
		
				ProcessHelper.CallProcesses (pobjCompileCalls, SolGenerator.CompileMaxWaitMilliseconds, true);
			}
		}
		
		
		private static void GenerateClasses 
		(
			string pstrLibraryName,
			List<XmlObject> pobjObjects, string pstrSetName, string pstrSetVersion,
			string pstrBaseClassName, GenerateClass pdelGenerateClass, ref List<ProcessStartInfo> pobjCompileCalls
		)
		{
			string strSNKFileName;
			string strSDKFolder;
			string strRuntimeFolder;
			
			DirectoryInfo dirSourcesDestinationFolder;
			
			ProcessStartInfo proInfo;
			
			
			dirSourcesDestinationFolder = Directory.CreateDirectory (
				SolGenerator.SourcesDestinationFolder + Path.DirectorySeparatorChar +
				pstrSetName + Path.DirectorySeparatorChar + 
				"Core" + Path.DirectorySeparatorChar + pstrLibraryName);
						
			strSNKFileName = string.Format ("{0}{1}{2}.{3}.{4}.snk", dirSourcesDestinationFolder.FullName, 
				Path.DirectorySeparatorChar, SolGenerator.Namespace, pstrSetName, pstrLibraryName);
			
			proInfo = new ProcessStartInfo ();
			
			SolGenerator.GetRuntimeToolsFolders (out strSDKFolder, out strRuntimeFolder);
			
			proInfo.FileName = string.Format ("\"{0}sn\"", strSDKFolder);
			proInfo.Arguments = string.Format (@"-k ""{0}""", strSNKFileName);
			
			pobjCompileCalls.Add (proInfo);
			
			try
			{
				foreach (XmlObject objObject in pobjObjects.FindAll (o => !o.IsArray))
				{
					pdelGenerateClass (File.CreateText (dirSourcesDestinationFolder.FullName + Path.DirectorySeparatorChar + pstrBaseClassName + objObject.Name + ".cs"), 
						SolGenerator.Namespace, pstrBaseClassName, objObject);
				}
				
				SolGenerator.GenerateAssemblyInfo (dirSourcesDestinationFolder, 
					string.Format ("Basic {0} for {1}.{2} generated by ROSSOX", 
						pstrLibraryName, SolGenerator.Namespace, pstrSetName), 
						string.Format ("{0} for {1}", pstrLibraryName, SolGenerator.Namespace), 
							SolGenerator.Namespace, pstrSetVersion);
			}
			catch (Exception excEx)
			{
				throw new GenericException (GenericException.CRI_FILE_ERROR, 
					string.Format ("No fueron generadas las clases para {0} debido a: {1}", SolGenerator.Namespace, excEx.Message), excEx);
			}
			
			SolGenerator.GenerateCallCompiler (dirSourcesDestinationFolder.FullName, pstrSetName, pstrLibraryName, strSNKFileName, ref pobjCompileCalls);
		}
		
		#endregion
		
		
		#region Funciones complementarias para generacion de codigo
		
		internal static void AddEntitiesUsings (ref TextWriter ptxtWriter, List<XmlMember> pobjMembers)
		{
			SolGenerator.AddComponentGroupUsings ("Entities", ref ptxtWriter, pobjMembers);
		}
		
		
		internal static void AddControllersUsings (ref TextWriter ptxtWriter, List<XmlMember> pobjMembers)
		{
			SolGenerator.AddComponentGroupUsings ("Controllers", ref ptxtWriter, pobjMembers);
		}
		
		
		internal static void AddDataAccessesUsings (ref TextWriter ptxtWriter, List<XmlMember> pobjMembers)
		{
			SolGenerator.AddComponentGroupUsings ("DataAccesses", ref ptxtWriter, pobjMembers);
		}
		
		
		private static void AddComponentGroupUsings (string pstrComponentGroupName, ref TextWriter ptxtWriter, List<XmlMember> pobjMembers)
		{			
			List<string> strCustomTypeImports;
			string strCustomTypeImport;
			
			StringBuilder stbResult;
			
			
			strCustomTypeImports = new List<string> ();
			
			stbResult = new StringBuilder ();
			
			
			foreach (XmlMember objMember in pobjMembers.FindAll (m => !string.IsNullOrEmpty (m.FromSet)))
			{
				strCustomTypeImport = string.Format ("{0}.{1}.{2}", SolGenerator.Namespace, objMember.FromSet, pstrComponentGroupName);
			
				if (!strCustomTypeImports.Contains (strCustomTypeImport))
				{
					strCustomTypeImports.Add (strCustomTypeImport);
					
					stbResult.AppendFormat ("using {0};", strCustomTypeImport);
					stbResult.AppendLine ();
				}
			}
			
			if (stbResult.Length > 0)
			{
				stbResult.AppendLine ();
				
				ptxtWriter.Write (stbResult.ToString ());
			}
		}
		
		#endregion
		
		
		#region Configuracion de la Generacion
		
		public static void DoIT (string pstrObjectProjectFileName)
		{
			XmlDocument xmlDoc;
			
			XmlHelper xmlEx;
			
			
			xmlEx = new XmlHelper ();
			xmlEx.ObjectName = "Configuración general de proyectos de objetos";
			
			xmlEx.Validate.FileExists (true, "Archivo", pstrObjectProjectFileName);
						
			#region Carga del Archivo de Proyecto
			
			try
			{
				xmlDoc = new XmlDocument ();
				xmlDoc.Load (pstrObjectProjectFileName);
				
				xmlEx.EvaluatedNode = xmlDoc.DocumentElement;
			}
			catch (Exception excEx)
			{
				throw new GenericException (GenericException.CRI_INVALID_FORMAT, "El archivo de proyecto tiene un formato invalido", excEx);
			}
			
			#endregion
			
			#region Inicializacion Basica del Generador de Soluciones
			
			SolGenerator.ObjectSetManager = new XmlObjectSetManager ();
			SolGenerator.MonoBinPath = xmlEx.GetAttributeValue (false, "monoBinPath", "Ruta de los ejecutables de Mono");
			SolGenerator.MSVstudioSDKBinPath = xmlEx.GetAttributeValue (false, "msVstudioSDKBinPath", "Ruta de los ejecutables del SDK de MS Visual Studio");
			SolGenerator._CompileMaxWaitMilliseconds = xmlEx.GetAttributeValueUInt16 (false, "compileMaxWaitMilliseconds", "Maximo tiempo de espera para compilación");
			
			#endregion
			
			#region Proceso de los proyectos habilitados
			
			foreach (XmlNode xmlObjectProject in xmlDoc.DocumentElement.SelectNodes ("ObjectProject[@enabled='true']"))
			{
				xmlEx.ObjectName = "Parametros del Proyecto";
				xmlEx.EvaluatedNode = xmlObjectProject;
			
				SolGenerator.ObjectSetManager.Clear ();
			
				SolGenerator.ProcessObjectProject (xmlEx);
			}
			
			#endregion
		}
		
		
		private static void ProcessObjectProject (XmlHelper pxmlExObjectProject)
		{
			string strTemp;
			string strTemp_I;
			
			DirectoryInfo dirSetFolder;
			
			DbGenerator objDbGenerator;
			
			DbProviders enuDbProviderType;
			
			
			#region Carga de los Object Sets
			
			dirSetFolder = pxmlExObjectProject.GetAttributeValueDirectory (true, "objectSetFolder", "Carpeta de Conjuntos de Objetos en XML");
			
			try
			{
				foreach (FileInfo strFileName in dirSetFolder.GetFiles ("*.xml"))
				{
					SolGenerator.ObjectSetManager.Add (strFileName.FullName);
				}
				
				SolGenerator.ObjectSetManager.Close ();
			}
			catch (Exception excEx)
			{
				throw new GenericException (GenericException.CRI_SYSTEM_ERROR, "No pudieron ser cargados los archivos de definición de objetos", excEx);
			}
			
			#endregion
			
			#region Carga de los parametros Basicos
			
			SolGenerator.DoCompile = pxmlExObjectProject.GetAttributeValueBool (true, "doCompile", "Indicador de si el Proyecto debe Compilarse").Value;
			SolGenerator.GenerateWebControls = pxmlExObjectProject.GetAttributeValueBool (false, "generateWebControls", "Indicador de si el Proyecto debe generar los controles de servidor web").Value;
			
			SolGenerator.Namespace = pxmlExObjectProject.GetAttributeValue (true, "namespace", "Espacio de Nombres del Proyecto");
			SolGenerator.LibrariesDestinationFolder = pxmlExObjectProject.GetAttributeValue (true, "librariesDestinationFolder", "Ubicación de la librerias generadas");
			SolGenerator.ReferenceAssembliesFolder = pxmlExObjectProject.GetAttributeValue (true, "referenceAssembliesFolder", "Ubicación de las librerias de referencia (ESF, .NET, Mono, Otros)");
			SolGenerator.SourcesDestinationFolder = pxmlExObjectProject.GetAttributeValue (true, "sourcesDestinationFolder", "Ubicación de los fuentes de las librerias generados");
			
			
			strTemp = pxmlExObjectProject.GetAttributeValue (true, "compilerType", "Tipo de Compilador utilizado, se recomienda Mono");
			
			try
			{
				SolGenerator.CompilerType = (CompilerTypes) Enum.Parse (typeof (CompilerTypes), strTemp, true);
			}
			catch (Exception excEx)
			{
				throw new GenericException (GenericException.CRI_INVALID_FORMAT, string.Format ("{0} no corresponde a un compilador soportado", strTemp), excEx);
			}
			
			#endregion
			
			#region Carga del Manejador de DB
			
			pxmlExObjectProject.Validate.FilledObject (true, "Parametros de Generación de la Base de Datos", pxmlExObjectProject.EvaluatedNode ["DbGenerator"]);
			
			pxmlExObjectProject.EvaluatedNode = pxmlExObjectProject.EvaluatedNode ["DbGenerator"];
			
			strTemp = pxmlExObjectProject.GetAttributeValue (true, "dbProviderType", "Tipo de Proveedor de Base de Datos");
			
			try
			{
				enuDbProviderType = (DbProviders) Enum.Parse (typeof (DbProviders), strTemp, true);
			}
			catch (Exception excEx)
			{
				throw new GenericException (GenericException.CRI_INVALID_FORMAT, 
					string.Format ("El valor {0} no corresponde a un tipo de base de datos registrado", strTemp), excEx);
			}			
			
			strTemp = pxmlExObjectProject.GetAttributeValue (true, "dataBaseName", "Nombre de la Base de Datos a Generar");
			strTemp_I = pxmlExObjectProject.GetAttributeValue (true, "connectionStringName", "Nombre de la Cadena de Conexión a la Base de Datos");
			
			switch (enuDbProviderType)
			{
				case DbProviders.MySql:
					objDbGenerator = new MySqlDbGenerator (strTemp, strTemp_I, SolGenerator.ObjectSetManager);
					break;
					
				default: 
					throw new GenericException (GenericException.CRI_UNSUPPORTED_ENVIRONMENT, string.Format ("No es soportada para generación de script para la base de datos {0}", enuDbProviderType));
			}
			
			if (pxmlExObjectProject.GetAttributeValueBool (true, "generateScript", "Indicador para Generar Script de Base de Datos").Value)
			{
				// TODO: Generar un metodo que tome el script generado y lo ejecute contra la base de datos.
				
				objDbGenerator.GenerateDbScripts (
					pxmlExObjectProject.GetAttributeValue (true, "scriptFileName", "Ruta del Script de Base de Datos generado"), 
					pxmlExObjectProject.GetAttributeValueBool (false, "includeCreateDeleteDB", "Indicador de si la base de datos se recrea", false).Value, 
					true, true, DbGenerator.GeneratorTypes.DeleteAllCreateAll);
			}
			
			#endregion
			
			#region Ajustes Finales y Convocacion
			
			SolGenerator.ConnectionStringName = objDbGenerator.ConnectionStringName;
			SolGenerator.DbParamsSeparator = objDbGenerator.ParamsSeparator;
			SolGenerator.DbNamesSeparator = objDbGenerator.NamesSeparator;
			SolGenerator.DbName = objDbGenerator.DataBaseName;

			SolGenerator.GenerateLibraries ();
			
			#endregion
		}
		
		#endregion
	}
}